home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / uip / ucbmail / head.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-03-28  |  6.0 KB  |  346 lines

  1. /*
  2.  *  H E A D . C 
  3.  *
  4.  *  EE/CIS Computer Lab
  5.  *  Department of Computer and Information Sciences
  6.  *  Department of Electrical Engineering
  7.  *  University of Delaware
  8.  *
  9.  *  REVISION HISTORY:
  10.  *
  11.  *  $Revision: 1.3 $
  12.  *
  13.  *  $Log:    head.c,v $
  14.  * Revision 1.3  86/01/07  13:50:48  galvin
  15.  * Change parse to have a return value.  Make it check to be sure the
  16.  * line it is passed is a valid "From" line.  If it can determine a
  17.  * date then return the date and 0, otherwise return 1.
  18.  * 
  19.  * Revision 1.2  86/01/07  13:46:02  galvin
  20.  * Added comment header for revision history.
  21.  * 
  22.  *
  23.  */
  24.  
  25. /*
  26.  * Copyright (c) 1980 Regents of the University of California.
  27.  * All rights reserved.  The Berkeley software License Agreement
  28.  * specifies the terms and conditions for redistribution.
  29.  */
  30.  
  31. #ifndef lint
  32. static char *sccsid = "@(#)head.c    5.2 (Berkeley) 6/21/85";
  33. #endif not lint
  34.  
  35. #include "./rcv.h"
  36. #include <ctype.h>
  37.  
  38. /*
  39.  * Mail -- a mail program
  40.  *
  41.  * Routines for processing and detecting headlines.
  42.  */
  43.  
  44. /*
  45.  * See if the passed line buffer is a mail header.
  46.  * Return true if yes.  Note the extreme pains to
  47.  * accomodate all funny formats.
  48.  */
  49.  
  50. ishead(linebuf)
  51.     char linebuf[];
  52. {
  53.     register char *cp;
  54.     struct headline hl;
  55.     char parbuf[BUFSIZ];
  56.  
  57.     cp = linebuf;
  58.     if (strncmp("From ", cp, 5) != 0)
  59.         return(0);
  60.     parse(cp, &hl, parbuf);
  61.     if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
  62.         fail(linebuf, "No from or date field");
  63.         return(0);
  64.     }
  65.     if (!isdate(hl.l_date)) {
  66.         fail(linebuf, "Date field not legal date");
  67.         return(0);
  68.     }
  69.     
  70.     /*
  71.      * I guess we got it!
  72.      */
  73.  
  74.     return(1);
  75. }
  76.  
  77. fail(linebuf, reason)
  78.     char linebuf[], reason[];
  79. {
  80.  
  81.     if (value("debug") == NOSTR)
  82.         return;
  83.     fprintf(stderr, "\"%s\"\nnot a header because %s\n", linebuf, reason);
  84. }
  85.  
  86. /*
  87.  * Split a headline into its useful components.
  88.  * Copy the line into dynamic string space, then set
  89.  * pointers into the copied line in the passed headline
  90.  * structure.  Actually, it scans.  Return 0 if we parsed, 1 otherwise.
  91.  */
  92.  
  93. parse(line, hl, pbuf)
  94.     char line[], pbuf[];
  95.     struct headline *hl;
  96. {
  97.     register char *cp, *dp;
  98.     char *sp;
  99.     char word[LINESIZE];
  100.  
  101.     hl->l_from = NOSTR;
  102.     hl->l_tty = NOSTR;
  103.     hl->l_date = NOSTR;
  104.     cp = line;
  105.     sp = pbuf;
  106.  
  107.     /*
  108.      * Skip the first "word" of the line, which should be "From"
  109.      * anyway.
  110.      */
  111.  
  112.     if (strncmp(cp, "From", 4) == 0) {
  113.     cp = nextword(cp, word);
  114.     dp = nextword(cp, word);
  115.     if (!equal(word, ""))
  116.         hl->l_from = copyin(word, &sp);
  117.     if (strncmp(dp, "tty", 3) == 0) {
  118.         cp = nextword(dp, word);
  119.         hl->l_tty = copyin(word, &sp);
  120.         if (cp != NOSTR)
  121.             hl->l_date = copyin(cp, &sp);
  122.     }
  123.     else
  124.         if (dp != NOSTR)
  125.             hl->l_date = copyin(dp, &sp);
  126.         return(0);
  127.     }
  128.     else
  129.         return(1);
  130. }
  131.  
  132. /*
  133.  * Copy the string on the left into the string on the right
  134.  * and bump the right (reference) string pointer by the length.
  135.  * Thus, dynamically allocate space in the right string, copying
  136.  * the left string into it.
  137.  */
  138.  
  139. char *
  140. copyin(src, space)
  141.     char src[];
  142.     char **space;
  143. {
  144.     register char *cp, *top;
  145.     register int s;
  146.  
  147.     s = strlen(src);
  148.     cp = *space;
  149.     top = cp;
  150.     strcpy(cp, src);
  151.     cp += s + 1;
  152.     *space = cp;
  153.     return(top);
  154. }
  155.  
  156. /*
  157.  * Test to see if the passed string is a ctime(3) generated
  158.  * date string as documented in the manual.  The template
  159.  * below is used as the criterion of correctness.
  160.  * Also, we check for a possible trailing time zone using
  161.  * the auxtype template.
  162.  */
  163.  
  164. #define    L    1        /* A lower case char */
  165. #define    S    2        /* A space */
  166. #define    D    3        /* A digit */
  167. #define    O    4        /* An optional digit or space */
  168. #define    C    5        /* A colon */
  169. #define    N    6        /* A new line */
  170. #define U    7        /* An upper case char */
  171.  
  172. char ctypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0};
  173. char tmztypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0};
  174.  
  175. isdate(date)
  176.     char date[];
  177. {
  178.     register char *cp;
  179.  
  180.     cp = date;
  181.     if (cmatch(cp, ctypes))
  182.         return(1);
  183.     return(cmatch(cp, tmztypes));
  184. }
  185.  
  186. /*
  187.  * Match the given string against the given template.
  188.  * Return 1 if they match, 0 if they don't
  189.  */
  190.  
  191. cmatch(str, temp)
  192.     char str[], temp[];
  193. {
  194.     register char *cp, *tp;
  195.     register int c;
  196.  
  197.     cp = str;
  198.     tp = temp;
  199.     while (*cp != '\0' && *tp != 0) {
  200.         c = *cp++;
  201.         switch (*tp++) {
  202.         case L:
  203.             if (c < 'a' || c > 'z')
  204.                 return(0);
  205.             break;
  206.  
  207.         case U:
  208.             if (c < 'A' || c > 'Z')
  209.                 return(0);
  210.             break;
  211.  
  212.         case S:
  213.             if (c != ' ')
  214.                 return(0);
  215.             break;
  216.  
  217.         case D:
  218.             if (!isdigit(c))
  219.                 return(0);
  220.             break;
  221.  
  222.         case O:
  223.             if (c != ' ' && !isdigit(c))
  224.                 return(0);
  225.             break;
  226.  
  227.         case C:
  228.             if (c != ':')
  229.                 return(0);
  230.             break;
  231.  
  232.         case N:
  233.             if (c != '\n')
  234.                 return(0);
  235.             break;
  236.         }
  237.     }
  238.     if (*cp != '\0' || *tp != 0)
  239.         return(0);
  240.     return(1);
  241. }
  242.  
  243. /*
  244.  * Collect a liberal (space, tab delimited) word into the word buffer
  245.  * passed.  Also, return a pointer to the next word following that,
  246.  * or NOSTR if none follow.
  247.  */
  248.  
  249. char *
  250. nextword(wp, wbuf)
  251.     char wp[], wbuf[];
  252. {
  253.     register char *cp, *cp2;
  254.  
  255.     if ((cp = wp) == NOSTR) {
  256.         copy("", wbuf);
  257.         return(NOSTR);
  258.     }
  259.     cp2 = wbuf;
  260.     while (!any(*cp, " \t") && *cp != '\0')
  261.         if (*cp == '"') {
  262.              *cp2++ = *cp++;
  263.              while (*cp != '\0' && *cp != '"')
  264.                  *cp2++ = *cp++;
  265.              if (*cp == '"')
  266.                  *cp2++ = *cp++;
  267.          } else
  268.              *cp2++ = *cp++;
  269.     *cp2 = '\0';
  270.     while (any(*cp, " \t"))
  271.         cp++;
  272.     if (*cp == '\0')
  273.         return(NOSTR);
  274.     return(cp);
  275. }
  276.  
  277. #ifdef NO_LIB
  278. /*
  279.  * Test to see if the character is an ascii alphabetic.
  280.  */
  281.  
  282. isalpha(c)
  283. {
  284.     register int ch;
  285.  
  286.     ch = raise(c);
  287.     return(ch >= 'A' && ch <= 'Z');
  288. }
  289.  
  290. /*
  291.  * Test to see if the character is an ascii digit.
  292.  */
  293.  
  294. isdigit(c)
  295. {
  296.     return(c >= '0' && c <= '9');
  297. }
  298. #endif NO_LIB
  299. /*
  300.  * Copy str1 to str2, return pointer to null in str2.
  301.  */
  302.  
  303. char *
  304. copy(str1, str2)
  305.     char *str1, *str2;
  306. {
  307.     register char *s1, *s2;
  308.  
  309.     s1 = str1;
  310.     s2 = str2;
  311.     while (*s1)
  312.         *s2++ = *s1++;
  313.     *s2 = 0;
  314.     return(s2);
  315. }
  316.  
  317. /*
  318.  * Is ch any of the characters in str?
  319.  */
  320.  
  321.  
  322. any(ch, str)
  323.         char *str;
  324. {
  325.         register char *f;
  326.         register c;
  327.  
  328.         f = str;
  329.         c = ch;
  330.         while (*f)
  331.                 if (c == *f++)
  332.                         return(1);
  333.         return(0);
  334. }
  335.  
  336.  
  337. /*
  338.  * Convert lower case letters to upper case.
  339.  */
  340.  
  341. raise(c)
  342.     register int c;
  343. {
  344.         return(islower(c) ? toupper(c) : c );
  345. }
  346.